Bug 132501 - Make utility window translate to tool window in win32
authorTor Lillqvist <tml@novell.com>
Sun, 5 Oct 2008 00:00:10 +0000 (00:00 +0000)
committerTor Lillqvist <tml@src.gnome.org>
Sun, 5 Oct 2008 00:00:10 +0000 (00:00 +0000)
2008-10-04  Tor Lillqvist  <tml@novell.com>

Bug 132501 - Make utility window translate to tool window in win32

Implement the utility window type hint. Such windows are kept on
top of other windows. Makes GIMP's toolbox and dock windows behave
more like in GNOME under metacity. Apply the same logic also to
windows marked with the dialog window type hint, and windows that
are transient for some other window. I'll call such windows
"transient-type" below.

* gdk/win32/gdkevents-win32.c (doesnt_want_key): Drop unused
variables.

(ensure_stacking_on_unminimize)
(ensure_stacking_on_window_pos_changing)
(ensure_stacking_on_activate_app): New functions to implement the
desired stacking order. Make sure that a window that is not
transient-type stays below any transient-type windows of the
application. When activating a non-transient-type window make sure
it rises as high as possible.

(gdk_event_translate): Call above functions on
WM_WINDOWPOSCHANGING, WM_ACTIVATEAPP and on WM_SIZE when
unminimizing. Improve debugging printout.

* gdk/win32/gdkwindow-win32.c (get_effective_window_decorations):
Handle utility windows like toolbar windows.

(gdk_window_new_internal) (update_style_bits): Give utility
windows the WS_EX_TOOLWINDOW extended style.

(gdk_window_set_title): If debugging "misc" or "events", make the
handle of top-level windows show up in their title bars. Very
useful when looking at debugging output.

(gdk_window_set_keep_above) (gdk_window_set_keep_below)
(gdk_window_set_modal_hint) (gdk_window_set_skip_taskbar_hint)
(gdk_window_set_skip_pager_hint): Add and improve debugging
printout.

(gdk_window_set_type_hint): Print hint symbolically in GDK_NOTE().

2008-10-04  Tor Lillqvist  <tml@novell.com>

* gdk/win32/gdkmain-win32.c (_gdk_win32_window_exstyle_to_string)
(_gdk_win32_window_pos_bits_to_string): New debugging printout
functions. Decode the WS_EX_* and SWP_* bits.

* gdk/win32/gdkprivate-win32.h: Declare them. Define
GDK_DEBUG_MISC_OR_EVENTS for use in GDK_NOTE() to match either
"misc" or "events".

svn path=/trunk/; revision=21587

ChangeLog
gdk/win32/gdkevents-win32.c
gdk/win32/gdkmain-win32.c
gdk/win32/gdkprivate-win32.h
gdk/win32/gdkwindow-win32.c

index 763281b512a68cb574290a12e90f5b9ac897e163..a4d41890b03fc155c0c8f66736e32e384dcf3af8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,56 @@
+2008-10-04  Tor Lillqvist  <tml@novell.com>
+
+       Bug 132501 - Make utility window translate to tool window in win32
+
+       Implement the utility window type hint. Such windows are kept on
+       top of other windows. Makes GIMP's toolbox and dock windows behave
+       more like in GNOME under metacity. Apply the same logic also to
+       windows marked with the dialog window type hint, and windows that
+       are transient for some other window. I'll call such windows
+       "transient-type" below.
+
+       * gdk/win32/gdkevents-win32.c (doesnt_want_key): Drop unused
+       variables.
+
+       (ensure_stacking_on_unminimize)
+       (ensure_stacking_on_window_pos_changing)
+       (ensure_stacking_on_activate_app): New functions to implement the
+       desired stacking order. Make sure that a window that is not
+       transient-type stays below any transient-type windows of the
+       application. When activating a non-transient-type window make sure
+       it rises as high as possible.
+
+       (gdk_event_translate): Call above functions on
+       WM_WINDOWPOSCHANGING, WM_ACTIVATEAPP and on WM_SIZE when
+       unminimizing. Improve debugging printout.
+
+       * gdk/win32/gdkwindow-win32.c (get_effective_window_decorations):
+       Handle utility windows like toolbar windows.
+
+       (gdk_window_new_internal) (update_style_bits): Give utility
+       windows the WS_EX_TOOLWINDOW extended style.
+
+       (gdk_window_set_title): If debugging "misc" or "events", make the
+       handle of top-level windows show up in their title bars. Very
+       useful when looking at debugging output.
+
+       (gdk_window_set_keep_above) (gdk_window_set_keep_below)
+       (gdk_window_set_modal_hint) (gdk_window_set_skip_taskbar_hint)
+       (gdk_window_set_skip_pager_hint): Add and improve debugging
+       printout.
+
+       (gdk_window_set_type_hint): Print hint symbolically in GDK_NOTE().
+
+2008-10-04  Tor Lillqvist  <tml@novell.com>
+
+       * gdk/win32/gdkmain-win32.c (_gdk_win32_window_exstyle_to_string)
+       (_gdk_win32_window_pos_bits_to_string): New debugging printout
+       functions. Decode the WS_EX_* and SWP_* bits.
+
+       * gdk/win32/gdkprivate-win32.h: Declare them. Define
+       GDK_DEBUG_MISC_OR_EVENTS for use in GDK_NOTE() to match either
+       "misc" or "events".
+
 2008-10-03  Matthias Clasen <mclasen@redhat.com>
 
        * gtk/gtkmodules.c (_gtk_modules_settings_changed): Add some
index 356d44c6f984e83a1a36905636a0c5b97df8645f..de104d3f02a22899d2748146803693095d02d3d8 100644 (file)
@@ -292,11 +292,7 @@ _gdk_win32_window_procedure (HWND   hwnd,
   retval = inner_window_procedure (hwnd, message, wparam, lparam);
   debug_indent -= 2;
 
-#ifdef _WIN64
-  GDK_NOTE (EVENTS, g_print (" => %I64d%s", retval, (debug_indent == 0 ? "\n" : "")));
-#else
-  GDK_NOTE (EVENTS, g_print (" => %ld%s", retval, (debug_indent == 0 ? "\n" : "")));
-#endif
+  GDK_NOTE (EVENTS, g_print (" => %I64d%s", (gint64) retval, (debug_indent == 0 ? "\n" : "")));
 
   return retval;
 }
@@ -1781,9 +1777,6 @@ static gboolean
 doesnt_want_key (gint mask,
                 MSG *msg)
 {
-  GdkWindow *modal_current = _gdk_modal_current ();
-  GdkWindow *window = (GdkWindow *) gdk_win32_handle_table_lookup ((GdkNativeWindow)msg->hwnd);
-
   return (((msg->message == WM_KEYUP || msg->message == WM_SYSKEYUP) &&
           !(mask & GDK_KEY_RELEASE_MASK)) ||
          ((msg->message == WM_KEYDOWN || msg->message == WM_SYSKEYDOWN) &&
@@ -2106,6 +2099,143 @@ generate_button_event (GdkEventType type,
     _gdk_event_button_generate (_gdk_display, event);
 }
 
+static void
+ensure_stacking_on_unminimize (MSG *msg)
+{
+  HWND rover;
+  HWND lowest_transient = NULL;
+
+  rover = msg->hwnd;
+  while ((rover = GetNextWindow (rover, GW_HWNDNEXT)))
+    {
+      GdkWindow *rover_gdkw = gdk_win32_handle_table_lookup (rover);
+
+      /* Checking window group not implemented yet */
+      if (rover_gdkw)
+       {
+         GdkWindowImplWin32 *rover_impl =
+           (GdkWindowImplWin32 *)((GdkWindowObject *)rover_gdkw)->impl;
+
+         if (rover_impl->type_hint == GDK_WINDOW_TYPE_HINT_UTILITY ||
+             rover_impl->type_hint == GDK_WINDOW_TYPE_HINT_DIALOG ||
+             rover_impl->transient_owner != NULL)
+           {
+             lowest_transient = rover;
+           }
+       }
+    }
+  if (lowest_transient != NULL)
+    {
+      GDK_NOTE (EVENTS, g_print (" restacking: %p", lowest_transient));
+      SetWindowPos (msg->hwnd, lowest_transient, 0, 0, 0, 0,
+                   SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
+    }
+}
+
+static gboolean
+ensure_stacking_on_window_pos_changing (MSG       *msg,
+                                       GdkWindow *window)
+{
+  GdkWindowImplWin32 *impl = (GdkWindowImplWin32 *)((GdkWindowObject *) window)->impl;
+  WINDOWPOS *windowpos = (WINDOWPOS *) msg->lParam;
+
+  if (GetActiveWindow () == msg->hwnd &&
+      impl->type_hint != GDK_WINDOW_TYPE_HINT_UTILITY &&
+      impl->type_hint != GDK_WINDOW_TYPE_HINT_DIALOG &&
+      impl->transient_owner == NULL)
+    {
+      /* Make sure the window stays behind any transient-type windows
+       * of the same window group.
+       *
+       * If the window is not active and being activated, we let
+       * Windows bring it to the top and rely on the WM_ACTIVATEAPP
+       * handling to bring any utility windows on top of it.
+       */
+      HWND rover;
+      gboolean restacking;
+
+      rover = windowpos->hwndInsertAfter;
+      restacking = FALSE;
+      while (rover)
+       {
+         GdkWindow *rover_gdkw = gdk_win32_handle_table_lookup (rover);
+
+         /* Checking window group not implemented yet */
+         if (rover_gdkw)
+           {
+             GdkWindowImplWin32 *rover_impl =
+               (GdkWindowImplWin32 *)((GdkWindowObject *)rover_gdkw)->impl;
+
+             if (rover_impl->type_hint == GDK_WINDOW_TYPE_HINT_UTILITY ||
+                 rover_impl->type_hint == GDK_WINDOW_TYPE_HINT_DIALOG ||
+                 rover_impl->transient_owner != NULL)
+               {
+                 restacking = TRUE;
+                 windowpos->hwndInsertAfter = rover;
+               }
+           }
+         rover = GetNextWindow (rover, GW_HWNDNEXT);
+       }
+
+      if (restacking)
+       {
+         GDK_NOTE (EVENTS, g_print (" restacking: %p", windowpos->hwndInsertAfter));
+         return TRUE;
+       }
+    }
+  return FALSE;
+}
+
+static void
+ensure_stacking_on_activate_app (MSG       *msg,
+                                GdkWindow *window)
+{
+  GdkWindowImplWin32 *impl = (GdkWindowImplWin32 *)((GdkWindowObject *) window)->impl;
+
+  if (impl->type_hint == GDK_WINDOW_TYPE_HINT_UTILITY ||
+      impl->type_hint == GDK_WINDOW_TYPE_HINT_DIALOG ||
+      impl->transient_owner != NULL)
+    {
+      SetWindowPos (msg->hwnd, HWND_TOP, 0, 0, 0, 0,
+                   SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
+      return;
+    }
+
+  if (IsWindowVisible (msg->hwnd) &&
+      gdk_win32_handle_table_lookup (GetActiveWindow ()))
+    {
+      /* This window is not a transient-type window and this or some
+       * other window in this app is the active window. Make sure this
+       * window is as visible as possible, just below the lowest
+       * transient-type window of this app.
+       */
+      HWND rover;
+
+      rover = msg->hwnd;
+      while ((rover = GetNextWindow (rover, GW_HWNDPREV)))
+       {
+         GdkWindow *rover_gdkw = gdk_win32_handle_table_lookup (rover);
+
+         /* Checking window group not implemented yet */
+         if (rover_gdkw)
+           {
+             GdkWindowImplWin32 *rover_impl =
+               (GdkWindowImplWin32 *)((GdkWindowObject *)rover_gdkw)->impl;
+
+             if (rover_impl->type_hint == GDK_WINDOW_TYPE_HINT_UTILITY ||
+                 rover_impl->type_hint == GDK_WINDOW_TYPE_HINT_DIALOG ||
+                 rover_impl->transient_owner != NULL)
+               {
+                 GDK_NOTE (EVENTS, g_print (" restacking: %p", rover));
+                 SetWindowPos (msg->hwnd, rover, 0, 0, 0, 0,
+                               SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
+                 break;
+               }
+           }
+       }
+    }
+}
+
 static gboolean
 gdk_event_translate (MSG  *msg,
                     gint *ret_valp)
@@ -2117,6 +2247,7 @@ gdk_event_translate (MSG  *msg,
   HCURSOR hcursor;
   BYTE key_state[256];
   HIMC himc;
+  WINDOWPOS *windowpos;
 
   GdkEvent *event;
 
@@ -2852,7 +2983,6 @@ gdk_event_translate (MSG  *msg,
       break;
 
     case WM_SYNCPAINT:
-
       sync_timer = SetTimer (GDK_WINDOW_HWND (window),
                             1,
                             200, sync_timer_proc);
@@ -2886,7 +3016,14 @@ gdk_event_translate (MSG  *msg,
       break;
 
     case WM_SHOWWINDOW:
-      GDK_NOTE (EVENTS, g_print (" %d", (int) msg->wParam));
+      GDK_NOTE (EVENTS, g_print (" %s %s",
+                                (msg->wParam ? "YES" : "NO"),
+                                (msg->lParam == 0 ? "ShowWindow" :
+                                 (msg->lParam == SW_OTHERUNZOOM ? "OTHERUNZOOM" :
+                                  (msg->lParam == SW_OTHERZOOM ? "OTHERZOOM" :
+                                   (msg->lParam == SW_PARENTCLOSING ? "PARENTCLOSING" :
+                                    (msg->lParam == SW_PARENTOPENING ? "PARENTOPENING" :
+                                     "???")))))));
 
       if (!(((GdkWindowObject *) window)->event_mask & GDK_STRUCTURE_MASK))
        break;
@@ -2927,7 +3064,6 @@ gdk_event_translate (MSG  *msg,
       break;
 
     case WM_SYSCOMMAND:
-
       switch (msg->wParam)
        {
        case SC_MINIMIZE:
@@ -2970,6 +3106,9 @@ gdk_event_translate (MSG  *msg,
          GdkWindowState withdrawn_bit =
            IsWindowVisible (msg->hwnd) ? GDK_WINDOW_STATE_WITHDRAWN : 0;
 
+         if (((GdkWindowObject *) window)->state & GDK_WINDOW_STATE_ICONIFIED)
+           ensure_stacking_on_unminimize (msg);
+
          if (!GDK_WINDOW_DESTROYED (window))
            handle_configure_event (msg, window);
          
@@ -3024,7 +3163,33 @@ gdk_event_translate (MSG  *msg,
       KillTimer (NULL, modal_timer);
       break;
 
-    case WM_WINDOWPOSCHANGED :
+    case WM_WINDOWPOSCHANGING:
+      GDK_NOTE (EVENTS, g_print (" %s %s %dx%d@%+d%+d now below %p",
+                                _gdk_win32_window_pos_bits_to_string (windowpos->flags),
+                                (windowpos->hwndInsertAfter == HWND_BOTTOM ? "BOTTOM" :
+                                 (windowpos->hwndInsertAfter == HWND_NOTOPMOST ? "NOTOPMOST" :
+                                  (windowpos->hwndInsertAfter == HWND_TOP ? "TOP" :
+                                   (windowpos->hwndInsertAfter == HWND_TOPMOST ? "TOPMOST" :
+                                    (sprintf (buf, "%p", windowpos->hwndInsertAfter),
+                                     buf))))),
+                                windowpos->cx, windowpos->cy, windowpos->x, windowpos->y,
+                                GetNextWindow (msg->hwnd, GW_HWNDPREV)));
+
+      return_val = ensure_stacking_on_window_pos_changing (msg, window);
+      break;
+
+    case WM_WINDOWPOSCHANGED:
+      GDK_NOTE (EVENTS, (windowpos = (WINDOWPOS *) msg->lParam,
+                        g_print (" %s %s %dx%d@%+d%+d",
+                                 _gdk_win32_window_pos_bits_to_string (windowpos->flags),
+                                 (windowpos->hwndInsertAfter == HWND_BOTTOM ? "BOTTOM" :
+                                  (windowpos->hwndInsertAfter == HWND_NOTOPMOST ? "NOTOPMOST" :
+                                   (windowpos->hwndInsertAfter == HWND_TOP ? "TOP" :
+                                    (windowpos->hwndInsertAfter == HWND_TOPMOST ? "TOPMOST" :
+                                     (sprintf (buf, "%p", windowpos->hwndInsertAfter),
+                                      buf))))),
+                                 windowpos->cx, windowpos->cy, windowpos->x, windowpos->y)));
+
       /* Once we've entered the moving or sizing modal loop, we won't
        * return to the main loop until we're done sizing or moving.
        */
@@ -3034,6 +3199,7 @@ gdk_event_translate (MSG  *msg,
        {
          if (((GdkWindowObject *) window)->event_mask & GDK_STRUCTURE_MASK)
            {
+             GDK_NOTE (EVENTS, g_print (" do magic"));
              if (((GdkWindowObject *) window)->resize_count > 1)
                ((GdkWindowObject *) window)->resize_count -= 1;
              
@@ -3457,11 +3623,17 @@ gdk_event_translate (MSG  *msg,
       break;
 
     case WM_ACTIVATE:
-
+      GDK_NOTE (EVENTS, g_print (" %s%s %p",
+                                (LOWORD (msg->wParam) == WA_ACTIVE ? "ACTIVE" :
+                                 (LOWORD (msg->wParam) == WA_CLICKACTIVE ? "CLICKACTIVE" :
+                                  (LOWORD (msg->wParam) == WA_INACTIVE ? "INACTIVE" : "???"))),
+                                HIWORD (msg->wParam) ? " minimized" : "",
+                                (HWND) msg->lParam));
       /* We handle mouse clicks for modally-blocked windows under WM_MOUSEACTIVATE,
        * but we still need to deal with alt-tab, or with SetActiveWindow() type
-       * situations. */
-      if (is_modally_blocked (window) && msg->wParam == WA_ACTIVE)
+       * situations.
+       */
+      if (is_modally_blocked (window) && LOWORD (msg->wParam) == WA_ACTIVE)
        {
          GdkWindow *modal_current = _gdk_modal_current ();
          SetActiveWindow (GDK_WINDOW_HWND (modal_current));
@@ -3479,6 +3651,13 @@ gdk_event_translate (MSG  *msg,
        _gdk_input_set_tablet_active ();
       break;
 
+    case WM_ACTIVATEAPP:
+      GDK_NOTE (EVENTS, g_print (" %s thread: %I64d",
+                                msg->wParam ? "YES" : "NO",
+                                (gint64) msg->lParam));
+
+      ensure_stacking_on_activate_app (msg, window);
+      break;
 
       /* Handle WINTAB events here, as we know that gdkinput.c will
        * use the fixed WT_DEFBASE as lcMsgBase, and we thus can use the
index be02856cf84bdaa1930f83204756086edaf6daa2..498a70926151ecac832733034b7636dea30575c5 100644 (file)
@@ -553,7 +553,7 @@ _gdk_win32_window_style_to_string (LONG style)
   buf[0] = '\0';
 
 #define BIT(x)                                         \
-  if (style & WS_ ## x)                        \
+  if (style & WS_ ## x)                                        \
     (bufp += sprintf (bufp, "%s" #x, s), s = "|")
 
   /* Note that many of the WS_* macros are in face several bits.
@@ -585,6 +585,81 @@ _gdk_win32_window_style_to_string (LONG style)
   return static_printf ("%s", buf);  
 }
 
+gchar *
+_gdk_win32_window_exstyle_to_string (LONG style)
+{
+  gchar buf[1000];
+  gchar *bufp = buf;
+  gchar *s = "";
+
+  buf[0] = '\0';
+
+#define BIT(x)                                         \
+  if (style & WS_EX_ ## x)                             \
+    (bufp += sprintf (bufp, "%s" #x, s), s = "|")
+
+  /* Note that many of the WS_EX_* macros are in face several bits.
+   * Handle just the individual bits here. Sort as in w32api's
+   * winuser.h.
+   */
+  BIT (ACCEPTFILES);
+  BIT (APPWINDOW);
+  BIT (CLIENTEDGE);
+  BIT (COMPOSITED);
+  BIT (CONTEXTHELP);
+  BIT (CONTROLPARENT);
+  BIT (DLGMODALFRAME);
+  BIT (LAYERED);
+  BIT (LAYOUTRTL);
+  BIT (LEFTSCROLLBAR);
+  BIT (MDICHILD);
+  BIT (NOACTIVATE);
+  BIT (NOINHERITLAYOUT);
+  BIT (NOPARENTNOTIFY);
+  BIT (RIGHT);
+  BIT (RTLREADING);
+  BIT (STATICEDGE);
+  BIT (TOOLWINDOW);
+  BIT (TOPMOST);
+  BIT (TRANSPARENT);
+  BIT (WINDOWEDGE);
+#undef BIT
+
+  return static_printf ("%s", buf);  
+}
+
+gchar *
+_gdk_win32_window_pos_bits_to_string (UINT flags)
+{
+  gchar buf[1000];
+  gchar *bufp = buf;
+  gchar *s = "";
+
+  buf[0] = '\0';
+
+#define BIT(x)                                         \
+  if (flags & SWP_ ## x)                               \
+    (bufp += sprintf (bufp, "%s" #x, s), s = "|")
+
+  BIT (DRAWFRAME);
+  BIT (FRAMECHANGED);
+  BIT (HIDEWINDOW);
+  BIT (NOACTIVATE);
+  BIT (NOCOPYBITS);
+  BIT (NOMOVE);
+  BIT (NOSIZE);
+  BIT (NOREDRAW);
+  BIT (NOZORDER);
+  BIT (SHOWWINDOW);
+  BIT (NOOWNERZORDER);
+  BIT (NOSENDCHANGING);
+  BIT (DEFERERASE);
+  BIT (ASYNCWINDOWPOS);
+#undef BIT
+
+  return static_printf ("%s", buf);  
+}
+
 gchar *
 _gdk_win32_rop2_to_string (int rop2)
 {
index 4196b4d5762b9412d64ed15a39c2560d9f8606eb..0d3fe99b98ffa76774dab21ef321893b766fb45d 100644 (file)
@@ -98,6 +98,7 @@
 #define GDK_DEBUG_EVENTS_OR_INPUT (GDK_DEBUG_EVENTS|GDK_DEBUG_INPUT)
 #define GDK_DEBUG_PIXMAP_OR_COLORMAP (GDK_DEBUG_PIXMAP|GDK_DEBUG_COLORMAP)
 #define GDK_DEBUG_MISC_OR_COLORMAP (GDK_DEBUG_MISC|GDK_DEBUG_COLORMAP)
+#define GDK_DEBUG_MISC_OR_EVENTS (GDK_DEBUG_MISC|GDK_DEBUG_EVENTS)
 
 #define GDK_TYPE_GC_WIN32              (_gdk_gc_win32_get_type ())
 #define GDK_GC_WIN32(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_GC_WIN32, GdkGCWin32))
@@ -311,6 +312,8 @@ gchar *_gdk_win32_line_style_to_string (GdkLineStyle line_style);
 gchar *_gdk_win32_gcvalues_mask_to_string (GdkGCValuesMask mask);
 gchar *_gdk_win32_window_state_to_string (GdkWindowState state);
 gchar *_gdk_win32_window_style_to_string (LONG style);
+gchar *_gdk_win32_window_exstyle_to_string (LONG style);
+gchar *_gdk_win32_window_pos_bits_to_string (UINT flags);
 gchar *_gdk_win32_drawable_description (GdkDrawable *d);
 
 gchar *_gdk_win32_rop2_to_string       (int          rop2);
index 78ca696eb35c2394538ec94a79d7128de149bbbb..14f5129a2c7f94cfb9aa5fcfb2229bc641cff08a 100644 (file)
 #include "gdkwindowimpl.h"
 #include "gdkprivate-win32.h"
 #include "gdkinput-win32.h"
-
-#if 0
-#include <gdk-pixbuf/gdk-pixbuf.h>
-#include <stdio.h>
-#endif
+#include "gdkenumtypes.h"
 
 static GdkColormap* gdk_window_impl_win32_get_colormap (GdkDrawable *drawable);
 static void         gdk_window_impl_win32_set_colormap (GdkDrawable *drawable,
@@ -54,9 +50,9 @@ static void gdk_window_impl_win32_finalize   (GObject                 *object);
 static gpointer parent_class = NULL;
 static GSList *modal_window_stack = NULL;
 
-static void     update_style_bits         (GdkWindow *window);
-static gboolean _gdk_window_get_functions (GdkWindow     *window,
-                                           GdkWMFunction *functions);
+static void     update_style_bits         (GdkWindow         *window);
+static gboolean _gdk_window_get_functions (GdkWindow         *window,
+                                           GdkWMFunction     *functions);
 
 #define WINDOW_IS_TOPLEVEL(window)                \
   (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
@@ -699,6 +695,9 @@ gdk_window_new_internal (GdkWindow     *parent,
   else
     impl->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
 
+  if (impl->type_hint == GDK_WINDOW_TYPE_HINT_UTILITY)
+    dwExStyle |= WS_EX_TOOLWINDOW;
+
   if (private->parent)
     private->parent->children = g_list_prepend (private->parent->children, window);
 
@@ -752,6 +751,9 @@ gdk_window_new_internal (GdkWindow     *parent,
                           hparent,
                           GDK_WINDOW_HWND (window)));
 
+  /* Add window handle to title */
+  GDK_NOTE (MISC_OR_EVENTS, gdk_window_set_title (window, title));
+
   g_free (wtitle);
 
   if (draw_impl->handle == NULL)
@@ -1852,16 +1854,15 @@ get_effective_window_decorations (GdkWindow       *window,
          return TRUE;
 
        case GDK_WINDOW_TYPE_HINT_TOOLBAR:
+       case GDK_WINDOW_TYPE_HINT_UTILITY:
          gdk_window_set_skip_taskbar_hint (window, TRUE);
-         *decoration = GDK_DECOR_ALL | GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE;
+         gdk_window_set_skip_pager_hint (window, TRUE);
+         *decoration = (GDK_DECOR_ALL | GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE);
          return TRUE;
 
-       case GDK_WINDOW_TYPE_HINT_UTILITY:
-         return FALSE;
-
        case GDK_WINDOW_TYPE_HINT_SPLASHSCREEN:
-         *decoration = (GDK_DECOR_ALL | GDK_DECOR_RESIZEH | GDK_DECOR_MENU
-                  | GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE);
+         *decoration = (GDK_DECOR_ALL | GDK_DECOR_RESIZEH | GDK_DECOR_MENU |
+                        GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE);
          return TRUE;
          
        case GDK_WINDOW_TYPE_HINT_DOCK:
@@ -1961,9 +1962,13 @@ gdk_window_set_title (GdkWindow   *window,
   GDK_NOTE (MISC, g_print ("gdk_window_set_title: %p: %s\n",
                           GDK_WINDOW_HWND (window), title));
   
+  GDK_NOTE (MISC_OR_EVENTS, title = g_strdup_printf ("%p %s", GDK_WINDOW_HWND (window), title));
+
   wtitle = g_utf8_to_utf16 (title, -1, NULL, NULL, NULL);
   API_CALL (SetWindowTextW, (GDK_WINDOW_HWND (window), wtitle));
   g_free (wtitle);
+
+  GDK_NOTE (MISC_OR_EVENTS, g_free ((char *) title));
 }
 
 void          
@@ -1992,6 +1997,8 @@ gdk_window_set_transient_for (GdkWindow *window,
   window_id = GDK_WINDOW_HWND (window);
   parent_id = parent != NULL ? GDK_WINDOW_HWND (parent) : NULL;
 
+  GDK_NOTE (MISC, g_print ("gdk_window_set_transient_for: %p: %p\n", window_id, parent_id));
+
   if (GDK_WINDOW_DESTROYED (window) || (parent && GDK_WINDOW_DESTROYED (parent)))
     {
       if (GDK_WINDOW_DESTROYED (window))
@@ -2879,19 +2886,29 @@ update_single_bit (LONG    *style,
 static void
 update_style_bits (GdkWindow *window)
 {
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowImplWin32 *impl = (GdkWindowImplWin32 *)private->impl;
   GdkWMDecoration decorations;
-  LONG old_style, new_style, exstyle;
+  LONG old_style, new_style, old_exstyle, new_exstyle;
   gboolean all;
   RECT rect, before, after;
 
   old_style = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
-  exstyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
+  old_exstyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE);
 
   GetClientRect (GDK_WINDOW_HWND (window), &before);
   after = before;
-  AdjustWindowRectEx (&before, old_style, FALSE, exstyle);
+  AdjustWindowRectEx (&before, old_style, FALSE, old_exstyle);
 
   new_style = old_style;
+  new_exstyle = old_exstyle;
+
+  if (private->window_type == GDK_WINDOW_TEMP ||
+      impl->type_hint == GDK_WINDOW_TYPE_HINT_UTILITY)
+    new_exstyle |= WS_EX_TOOLWINDOW;
+  else
+    new_exstyle &= ~WS_EX_TOOLWINDOW;
+
   if (get_effective_window_decorations (window, &decorations))
     {
       all = (decorations & GDK_DECOR_ALL);
@@ -2903,21 +2920,34 @@ update_style_bits (GdkWindow *window)
       update_single_bit (&new_style, all, decorations & GDK_DECOR_MAXIMIZE, WS_MAXIMIZEBOX);
     }
 
-  if (old_style == new_style)
+  if (old_style == new_style && old_exstyle == new_exstyle )
     {
       GDK_NOTE (MISC, g_print ("update_style_bits: %p: no change\n",
                               GDK_WINDOW_HWND (window)));
       return;
     }
 
-  GDK_NOTE (MISC, g_print ("update_style_bits: %p: %s => %s\n",
-                          GDK_WINDOW_HWND (window),
-                          _gdk_win32_window_style_to_string (old_style),
-                          _gdk_win32_window_style_to_string (new_style)));
+  if (old_style != new_style)
+    {
+      GDK_NOTE (MISC, g_print ("update_style_bits: %p: STYLE: %s => %s\n",
+                              GDK_WINDOW_HWND (window),
+                              _gdk_win32_window_style_to_string (old_style),
+                              _gdk_win32_window_style_to_string (new_style)));
+      
+      SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, new_style);
+    }
 
-  SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, new_style);
+  if (old_exstyle != new_exstyle)
+    {
+      GDK_NOTE (MISC, g_print ("update_style_bits: %p: EXSTYLE: %s => %s\n",
+                              GDK_WINDOW_HWND (window),
+                              _gdk_win32_window_exstyle_to_string (old_exstyle),
+                              _gdk_win32_window_exstyle_to_string (new_exstyle)));
+      
+      SetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE, new_exstyle);
+    }
 
-  AdjustWindowRectEx (&after, new_style, FALSE, exstyle);
+  AdjustWindowRectEx (&after, new_style, FALSE, new_exstyle);
 
   GetWindowRect (GDK_WINDOW_HWND (window), &rect);
   rect.left += after.left - before.left;
@@ -3492,13 +3522,18 @@ gdk_window_unfullscreen (GdkWindow *window)
 }
 
 void
-gdk_window_set_keep_above (GdkWindow *window, gboolean setting)
+gdk_window_set_keep_above (GdkWindow *window,
+                          gboolean   setting)
 {
   g_return_if_fail (GDK_IS_WINDOW (window));
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
+  GDK_NOTE (MISC, g_print ("gdk_window_set_keep_above: %p: %s\n",
+                          GDK_WINDOW_HWND (window),
+                          setting ? "YES" : "NO"));
+
   if (GDK_WINDOW_IS_MAPPED (window))
     {
       API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window),
@@ -3513,13 +3548,18 @@ gdk_window_set_keep_above (GdkWindow *window, gboolean setting)
 }
 
 void
-gdk_window_set_keep_below (GdkWindow *window, gboolean setting)
+gdk_window_set_keep_below (GdkWindow *window,
+                          gboolean   setting)
 {
   g_return_if_fail (GDK_IS_WINDOW (window));
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
+  GDK_NOTE (MISC, g_print ("gdk_window_set_keep_below: %p: %s\n",
+                          GDK_WINDOW_HWND (window),
+                          setting ? "YES" : "NO"));
+
   if (GDK_WINDOW_IS_MAPPED (window))
     {
       API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window),
@@ -3564,6 +3604,10 @@ gdk_window_set_modal_hint (GdkWindow *window,
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
+  GDK_NOTE (MISC, g_print ("gdk_window_set_modal_hint: %p: %s\n",
+                          GDK_WINDOW_HWND (window),
+                          modal ? "YES" : "NO"));
+
   private = (GdkWindowObject*) window;
 
   if (modal == private->modal_hint)
@@ -3602,13 +3646,13 @@ gdk_window_set_skip_taskbar_hint (GdkWindow *window,
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
+  GDK_NOTE (MISC, g_print ("gdk_window_set_skip_taskbar_hint: %p: %s, doing nothing\n",
+                          GDK_WINDOW_HWND (window),
+                          skips_taskbar ? "YES" : "NO"));
+
   // ### TODO: Need to figure out what to do here.
   return;
 
-  GDK_NOTE (MISC, g_print ("gdk_window_set_skip_taskbar_hint: %p: %s\n",
-                          GDK_WINDOW_HWND (window),
-                          skips_taskbar ? "TRUE" : "FALSE"));
-
   if (skips_taskbar)
     {
       if (owner == NULL)
@@ -3642,6 +3686,10 @@ gdk_window_set_skip_pager_hint (GdkWindow *window,
                                gboolean   skips_pager)
 {
   g_return_if_fail (GDK_IS_WINDOW (window));
+
+  GDK_NOTE (MISC, g_print ("gdk_window_set_skip_pager_hint: %p: %s, doing nothing\n",
+                          GDK_WINDOW_HWND (window),
+                          skips_pager ? "YES" : "NO"));
 }
 
 void
@@ -3653,8 +3701,15 @@ gdk_window_set_type_hint (GdkWindow        *window,
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
-  GDK_NOTE (MISC, g_print ("gdk_window_set_type_hint: %p: %d\n",
-                          GDK_WINDOW_HWND (window), hint));
+  GDK_NOTE (MISC,
+           G_STMT_START{
+             static GEnumClass *class = NULL;
+             if (!class)
+               class = g_type_class_ref (GDK_TYPE_WINDOW_TYPE_HINT);
+             g_print ("gdk_window_set_type_hint: %p: %s\n",
+                      GDK_WINDOW_HWND (window),
+                      g_enum_get_value (class, hint)->value_name);
+           }G_STMT_END);
 
   ((GdkWindowImplWin32 *)((GdkWindowObject *)window)->impl)->type_hint = hint;